/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  init.h
 *        \brief  This is a C language initialize export module.
 *       \author  Lamdonn
 *      \version  1.0.0
 *      \license  GPL-2.0
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#ifndef __init_H
#define __init_H

/* version infomation */

#define INIT_V_MAJOR                        1
#define INIT_V_MINOR                        0
#define INIT_V_PATCH                        0

/* ***** Important!!! ***** 
 * Please make sure that the init module is compiled in a higher order than the files using the init module.
 */

/* Define anonymous variable format */
#define __INIT_ANONY(type, var, line)   type var##line
#define INIT_ANONY_DEFINE(type, var)    __INIT_ANONY(type, var, __LINE__)

/* Special instructions for compilation */
#if defined(__CC_ARM) || defined(__GNUC__) /* ARM,GCC*/
    #define INIT_SECTION(x)             __attribute__((section(x)))
    #define INIT_USED                   __attribute__((used))
#elif defined (__ICCARM__)              /*IAR */
    #define INIT_SECTION(x)             @ x
    #define INIT_USED                   __root
#else
    #error "Current tool chain haven't supported yet!"
#endif

/* Initialization function format */
typedef void (*init_handler_t)(void);

/* Initialization structure definition */
typedef struct {
    init_handler_t handler;
} init_item;

/* Initialize export instead of macro definition */
#define __initialize(func, level) \
    INIT_USED INIT_ANONY_DEFINE(const init_item, init_item_##func) \
    INIT_SECTION("init."level) = {func}

/**
 *  \brief different levels of initialization are exported. The smaller the number, the more priority the initialization will be executed.
 *  \param[in] func: initialization function that needs to be executed
 *  \return none
 */
#define init_export_hardware(func)          __initialize(func, "1")
#define init_export_driver(func)            __initialize(func, "2")
#define init_export_system(func)            __initialize(func, "3")
#define init_export_module(func)            __initialize(func, "4")
#define init_export_app(func)               __initialize(func, "5")

/**
 *  \brief All initialization functions are called in this function, 
           this function needs to be called as early as possible to execute each initialization function.
 *  \return none
 */
void init_execute(void);
    
#endif
